package com.geeguo.ebuilder.client.business.system.webmodule.service.impl;

import com.geeguo.ebuilder.client.base.core.dictionary.ModuleTypeEnum;
import com.geeguo.ebuilder.client.base.redis.utils.CacheKeyFactory;
import com.geeguo.ebuilder.client.base.security.model.LoginUser;
import com.geeguo.ebuilder.client.base.tenant.model.DataContext;
import com.geeguo.ebuilder.client.business.system.rolewebmodule.service.RoleWebModuleService;
import com.geeguo.ebuilder.client.business.system.webmodule.model.*;
import com.geeguo.ebuilder.client.business.system.webmodule.remote.WebModuleApi;
import com.geeguo.ebuilder.client.business.system.webmodule.service.WebModuleService;
import com.geeguo.ebuilder.core.common.action.ActionResult;
import com.geeguo.ebuilder.core.common.utils.key.UUIDCheckUtils;
import com.geeguo.ebuilder.core.redis.service.RedisCacheService;
import com.geeguo.ebuilder.core.common.utils.GsonUtils;
import com.geeguo.ebuilder.core.redis.constants.CacheTimeConstants;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class WebModuleServiceImpl implements WebModuleService {

    @Autowired
    private WebModuleApi webModuleApi;
    @Autowired
    private RedisCacheService redisCacheService;
    @Autowired
    private RoleWebModuleService roleWebModuleService;

    @Override
    public List<WebModuleBO> listAll(DataContext dataContext) {
        List<WebModuleBO> result = new ArrayList<>();
        ActionResult<List<WebModuleRO>> actionResult = webModuleApi.listAll();
        if (actionResult.isSuccess()) {
            List<WebModuleRO> list = actionResult.getData();
            if (list != null && !list.isEmpty()) {
                result = WebModuleConverter.INSTANCE.convertROList2BOList(list);
            }
        }
        return result;
    }

    @Override
    public List<WebModuleVO> listAllTree(DataContext dataContext) {
        List<WebModuleVO> result = new ArrayList<>();
        List<WebModuleBO> moduleList = listAll(dataContext);
        if (moduleList != null && !moduleList.isEmpty()) {
            Map<String, WebModuleVO> dataMapping = new HashMap<>();
            for (WebModuleBO item : moduleList) {
                WebModuleVO module = WebModuleConverter.INSTANCE.convert2VO(item);
                if (UUIDCheckUtils.check(module.getParentId())) {
                    WebModuleVO parent = dataMapping.get(module.getParentId());
                    if (parent != null) {
                        parent.addChild(module);
                    }
                } else {
                    result.add(module);
                }
                dataMapping.put(module.getId(), module);
            }
        }
        return result;
    }

    @Override
    public List<WebModuleBO> listByUser(LoginUser loginUser, DataContext dataContext) {
        List<WebModuleBO> result = null;
        String cacheKey = CacheKeyFactory.INSTANCE.getUserWebModuleList(loginUser.getUserId(), dataContext);
        String cacheJson = redisCacheService.get(cacheKey);
        if (StringUtils.isNotEmpty(cacheJson)) {
            List<WebModuleCO> list = GsonUtils.fromJson(cacheJson, new TypeToken<List<WebModuleCO>>(){});
            result = WebModuleConverter.INSTANCE.convertCOList2BOList(list);
        }
        if (result == null) {
            result = new ArrayList<>();
            List<WebModuleBO> allList = listAll(dataContext);
            if (loginUser.isSuperAdmin()) {
                result.addAll(allList);
            } else {
                List<String> userModuleIds = roleWebModuleService.listModuleIdByUser(loginUser.getUserId(), dataContext);
                if (CollectionUtils.isNotEmpty(userModuleIds)) {
                    for (WebModuleBO item : allList) {
                        for (String moduleId : userModuleIds) {
                            if (item.getId().equals(moduleId)) {
                                result.add(item);
                                break;
                            }
                        }
                    }
                }
            }
            cacheJson = GsonUtils.toJson(WebModuleConverter.INSTANCE.convertBOList2COList(result));
            redisCacheService.set(cacheKey, cacheJson, CacheTimeConstants.CACHE_HOUR);
        }
        return result;
    }

    @Override
    public List<WebModuleBO> listMenuByUser(LoginUser loginUser, DataContext dataContext) {
        List<WebModuleBO> result = new ArrayList<>();
        List<WebModuleBO> moduleList = listByUser(loginUser, dataContext);
        if (moduleList != null && !moduleList.isEmpty()) {
            for (WebModuleBO item : moduleList) {
                if (item.getType() != ModuleTypeEnum.Function.getValue()) {
                    result.add(item);
                }
            }
        }
        return result;
    }

    @Override
    public Set<String> listPermissionCodeByUser(LoginUser loginUser, DataContext dataContext) {
        Set<String> result = new HashSet<>();
        List<WebModuleBO> moduleList = listByUser(loginUser, dataContext);
        if (moduleList != null && !moduleList.isEmpty()) {
            for (WebModuleBO item : moduleList) {
                if (StringUtils.isNotEmpty(item.getPermissionCode())) {
                    result.add(item.getPermissionCode());
                }
            }
        }
        return result;
    }

    @Override
    public void removeCachedUserWebModules(LoginUser loginUser, DataContext dataContext) {
        redisCacheService.del(CacheKeyFactory.INSTANCE.getUserWebModuleList(loginUser.getUserId(), dataContext));
    }
}